package com.project_doctor.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.project_doctor.common.RedisConst;
import com.project_doctor.mapper.ResidentMapper;
import com.project_doctor.mapper.TagMapper;
import com.project_doctor.pojo.Contract;
import com.project_doctor.pojo.Resident;
import com.project_doctor.pojo.Tag;
import com.project_doctor.pojo.dto.*;
import com.project_doctor.pojo.status.ServiceStatus;
import com.project_doctor.pojo.vo.ContractDetailVO;
import com.project_doctor.pojo.vo.ContractVO;
import com.project_doctor.pojo.vo.DetailsVO;
import com.project_doctor.service.ContractService;
import com.project_doctor.mapper.ContractMapper;
import com.project_doctor.service.ResidentService;
import com.project_doctor.service.TagService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.Period;
import java.time.ZoneId;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static cn.hutool.core.date.DateTime.now;

/**
* @author xixif
* @description 针对表【t_contract(签约服务记录表)】的数据库操作Service实现
* @createDate 2025-06-10 18:51:42
*/
@Service
@Slf4j
public class ContractServiceImpl extends ServiceImpl<ContractMapper, Contract>
    implements ContractService{

    @Autowired
    private ContractMapper contractMapper;
    @Autowired
    private ResidentMapper residentMapper;
    @Autowired
    private ResidentService residentService;
    @Autowired
    private TagMapper tagMapper;
    @Autowired
    private TagService tagService;

    @Override
    public List<ContractInfoDTO> getContractInfoByResidentId(Integer residentId) {
        return contractMapper.selectContractInfoByResidentIdSimple(residentId);
    }

    @Override
    @Cacheable(cacheNames = RedisConst.DOCTOR_PENDING_LIST,keyGenerator = "keyGenerator")
    public Page<ContractVO> getAllContract(Integer pageNum, Integer pageSize, ContractQueryDTO queryDTO) {
        // 处理日期范围
        if (queryDTO.getDate() != null && queryDTO.getDate().length == 2) {
            try {
                // 前端传递的日期字符串转换为Date对象
                java.text.SimpleDateFormat sdf = new java.text.SimpleDateFormat("yyyy-MM-dd");
                queryDTO.setStartDate(sdf.parse(queryDTO.getDate()[0]));

                // 结束日期加上23:59:59以包含整天
                java.util.Calendar cal = java.util.Calendar.getInstance();
                cal.setTime(sdf.parse(queryDTO.getDate()[1]));
                cal.set(java.util.Calendar.HOUR_OF_DAY, 23);
                cal.set(java.util.Calendar.MINUTE, 59);
                cal.set(java.util.Calendar.SECOND, 59);
                queryDTO.setEndDate(cal.getTime());
            } catch (Exception e) {
                log.error("日期格式转换失败: {}", e.getMessage());
            }
        }

        Page<ContractVO> page = new Page<>(pageNum, pageSize);
        return page.setRecords(contractMapper.selectAllContract(page, queryDTO));
    }


    /**
     * 获取签约详情
     * @return
     */
    @Override
    @Cacheable(cacheNames = RedisConst.CONTRACTING_DETAIL,keyGenerator = "keyGenerator")
    public List<ContractDetailVO> getAllContractDetail(Integer id) {
        return contractMapper.selectAllContractDetail(id); // 调用mapper层
    }


    /**
     * 添加签约服务记录
     * @param contractDTO
     */
    @Override
    @Transactional
    @CacheEvict(cacheNames = {"doctorPending:list","contracting:detail"}, allEntries = true)// 清除缓存
    public void saveContract(ContractDTO contractDTO) {
        try {

            // 获取 DTO 中的 birthDate（Date 类型）
            Date birthDate = contractDTO.getBirthdate();
            if (birthDate != null) {
                // 将 Date 转换为 LocalDate
                LocalDate localDate = birthDate.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                LocalDate currentLocalDate = LocalDate.now();

                // 计算年龄
                Period period = Period.between(localDate, currentLocalDate);
                int age = period.getYears();
                contractDTO.setAge(age); // 设置年龄到 DTO
            }

            if (contractDTO.getResidentId() != null){ // 判断 residentId 是否为空

                Resident resident = new Resident();//  创建 residual 实体对象
                resident.setId(contractDTO.getId());//  设置 residualId
                resident.setIdCard(contractDTO.getIdCard());// 设置身份证
                resident.setPhone(contractDTO.getPhone());//  设置手机号
                resident.setGender(contractDTO.getGender());// 设置性别
                resident.setAge(contractDTO.getAge());
                resident.setBirthdate(contractDTO.getBirthdate());//  设置生日
                resident.setAddress(contractDTO.getAddress());//  设置地址
                residentMapper.updateById(resident);// 更新 residual


                LambdaQueryWrapper<Tag> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(Tag::getRefId,contractDTO.getResidentId());
                tagMapper.delete(wrapper);

                if (contractDTO.getTags() != null){


                    List<Tag> collect = contractDTO.getTags().stream().map(tagName -> {
                        Tag tag = new Tag();
                        tag.setRefId(contractDTO.getResidentId());
                        tag.setRefType(1);
                        tag.setName(tagName);
                        tag.setAddedBy("admin");
                        tag.setLastModified(new Date());//  设置最后修改时间
                        return tag;
                    }).collect(Collectors.toList());
                    tagMapper.insertBatch(collect);
                }


                // 更新合同信息（仅非空字段）
                if (contractDTO.getId() != null) {
                    Contract tContract = new Contract();
                    tContract.setId(contractDTO.getId());

                    // 仅对非空字段赋值
                    if (contractDTO.getInst() != null) {
                        tContract.setInstId(contractDTO.getInst());
                    }
                    if (contractDTO.getDoctor() != null) {
                        tContract.setDoctorId(contractDTO.getDoctor());
                    }
                    if (contractDTO.getPackageId() != null) {
                        tContract.setPackageId(contractDTO.getPackageId());
                    }
                    if (contractDTO.getTeam() != null) {
                        tContract.setTeamId(contractDTO.getTeam());
                    }
                    tContract.setEffectiveDate(contractDTO.getEffectiveDate());
                    tContract.setRemark(contractDTO.getRemark());

                    contractMapper.updateById(tContract);
                }
            }

        } catch (Exception e) {
            // 日志记录异常
            log.error("保存合同失败: {}",e);
            throw new RuntimeException("数据保存失败，请重试");
        }
    }


    // 审核签约服务记录
    @Override
    public void approveContract(ContractApproveDTO approveDTO) {

        LambdaQueryWrapper<Contract> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Contract::getId,approveDTO.getId());// 设置合同ID


        Contract contract = contractMapper.selectOne(wrapper);// 查询合同信息
        if (contract != null){
            contract.setContractStatus(approveDTO.getStatus());// 设置审核状态
            contract.setRemark(approveDTO.getRemark());// 设置审核备注
            contractMapper.updateById(contract);// 更新合同信息
        }else{
            throw new RuntimeException("合同不存在");
        }

    }

    // 拒绝签约服务记录
    @Override
    public void rejectContract(ContractRejectDTO rejectDTO) {
        LambdaQueryWrapper<Contract> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Contract::getId,rejectDTO.getId());// 设置合同ID


        Contract rejectcontract = contractMapper.selectOne(wrapper);
        if (rejectcontract != null) {
            rejectcontract.setContractStatus(rejectDTO.getContractStatus());
            contractMapper.updateById(rejectcontract);
        }else {
            throw new RuntimeException("合同不存在");
        }
    }

    @Override
    public Page<ContractVO> getContractVoList(ContractQueryDTO queryDTO, Integer pageNum, Integer pageSize) {
        QueryWrapper<Contract> wrapper = new QueryWrapper<>();
        this.buildQueryConditions(wrapper,queryDTO);
        wrapper.notIn("c.service_status", queryDTO.getExcludeStatusList());
        // 排序
        wrapper.orderByDesc("c.apply_time");
        Page<ContractVO> page = new Page<>(pageNum,pageSize);
        return contractMapper.selectContractVoList(page,wrapper);
    }
    private void buildQueryConditions(QueryWrapper<Contract> wrapper, ContractQueryDTO queryDTO) {
        // 状态筛选
        if (StringUtils.isNotBlank(queryDTO.getStatus())) {
            wrapper.eq("s.id", queryDTO.getStatus());
        }

        // 机构筛选
        if (StringUtils.isNotBlank(queryDTO.getInstitution())) {
            wrapper.eq("i.id", queryDTO.getInstitution());
        }

        // 团队筛选
        if (StringUtils.isNotBlank(queryDTO.getTeam())) {
            wrapper.eq("t.id", queryDTO.getTeam());
        }

        // 服务包筛选
        if (StringUtils.isNotBlank(queryDTO.getPackageInfo())) {
            wrapper.eq("p.id", queryDTO.getPackageInfo());
        }

        // 时间范围筛选
        if (queryDTO.getStartTime() != null) {
            wrapper.ge("c.service_time", queryDTO.getStartTime());
        }
        if (queryDTO.getEndTime() != null) {
            wrapper.le("c.service_time", queryDTO.getEndTime());
        }

        // 关键字搜索 (姓名/电话/身份证)
        if (StringUtils.isNotBlank(queryDTO.getKeyword())) {
            wrapper.and(w -> w
                    .like("r.id", queryDTO.getKeyword())
                    .or()
                    .like("r.name", queryDTO.getKeyword())
                    .or()
                    .like("r.phone", queryDTO.getKeyword())
                    .or()
                    .like("r.id_card", queryDTO.getKeyword())
            );
        }
    }


    @Override
    public DetailsVO selectContractDetail(Integer contractId) {
        DetailsVO detailsVO = contractMapper.selectContractDetail(contractId);
        detailsVO.setTags(tagService.selectTagsList(detailsVO.getResidentId()));
        return detailsVO;
    }

    @Override
    public void updateService(DetailsDTO dto) {
        LambdaUpdateWrapper<Contract> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Contract::getId,dto.getContractId())
                .set(Contract::getInstId,dto.getInstitutionId())
                .set(Contract::getServiceTime,dto.getAppointmentTime())
                .set(Contract::getTeamId,dto.getTeamId())
                .set(Contract::getDoctorId,dto.getDoctorId())
                .set(Contract::getPackageId,dto.getPackageId())
                .set(Contract::getServiceId,dto.getServiceId())
                .set(Contract::getServiceRemark,dto.getServiceRemark())
                .set(Contract::getAddressId,dto.getAddressId());
        contractMapper.update(null,wrapper);
    }

    @Override
    public void addService(DetailsDTO dto) {
        residentService.updateService(dto);
        Contract contract = new Contract();
        contract.setResidentId(dto.getResidentId());
        contract.setInstId(dto.getInstitutionId());
        contract.setServiceTime(dto.getAppointmentTime());
        contract.setTeamId(dto.getTeamId());
        contract.setDoctorId(dto.getDoctorId());
        contract.setPackageId(dto.getPackageId());
        contract.setServiceId(dto.getServiceId());
        contract.setServiceRemark(dto.getServiceRemark());
        contract.setAddressId(dto.getAddressId());
        contract.setApplyTime(now());
        contract.setServiceStatus(ServiceStatus.PENDING_REVIEW.getKey());
        contractMapper.insert(contract);

    }

    @Override
    public void updateApproved(Integer contractId ,String  userName) {
        LambdaUpdateWrapper<Contract> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Contract::getId,contractId)
                .set(Contract::getServiceStatus,ServiceStatus.PENDING_SERVICE.getKey())
                .set(Contract::getAuditTime,now())
                .set(Contract::getAuditName,userName);
        contractMapper.update(null,wrapper);
    }


    @Override
    public void updateComplete(Integer contractId) {
        LambdaUpdateWrapper<Contract> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Contract::getId,contractId)
                .set(Contract::getServiceStatus,ServiceStatus.COMPLETED.getKey())
                .set(Contract::getCompletionTime,now());
        contractMapper.update(null,wrapper);
    }

    @Override
    public void updateCancel(CancelDTO dto) {
        LambdaUpdateWrapper<Contract> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Contract::getId,dto.getContractId())
                .set(Contract::getServiceStatus,ServiceStatus.CANCELED.getKey())
                .set(Contract::getCancellationTime,now())
                .set(Contract::getCancellationReason,dto.getCancelReason());
        contractMapper.update(null,wrapper);
    }
    @Override
    public void updateReject(RejectDTO dto) {
        LambdaUpdateWrapper<Contract> wrapper = new LambdaUpdateWrapper<>();
        wrapper.eq(Contract::getId,dto.getContractId())
                .set(Contract::getServiceStatus,ServiceStatus.REJECTED.getKey())
                .set(Contract::getRejectionReason,dto.getRejectReason())
                .set(Contract::getAuditTime,now())
                .set(Contract::getAuditName,dto.getUserName());
        contractMapper.update(null,wrapper);
    }
}




